package com.ccqlk.basemainapp.mas;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.idev.excel.ExcelWriter;
import cn.idev.excel.FastExcel;
import cn.idev.excel.FastExcelFactory;
import cn.idev.excel.support.ExcelTypeEnum;
import cn.idev.excel.write.metadata.WriteSheet;
import cn.idev.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Slf4j
public class 云MAS批量创建导出任务_云端数据 {
    private static final String COOKIE = "WT_FPC=id=2d411200e10a9e5b2301736497534816:lv=1736497579833:ss=1736497534816; SESSION=2b283772-aaee-4aa4-9c41-c6e6ff3e91dd; JSESSIONID=E3A4C5DBCE1B701104C54AD9CFC85FB8";
    private static final String DUAN_KOU = "106575637604";
    private static final String ENTERPRISE_NAME = "中国人民解放军陆军军医大学第二附属医院" + DUAN_KOU;
    private static final String MODE = "secPlat";
    private static final String START_DATE = "2025-06-10";
    private static final String END_DATE = "2025-06-20";

    private static final String BASE_FILE_URL = "C:/Users/13525/Documents";
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    private static final String FILE_DOWNLOAD_URL = "https://mas.10086.cn/ec/cmEcBill/downloadFile.ajax?url=%s";
    private static final String IP_REGEX = "\\b((25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]?\\d)\\.){3}(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]?\\d)\\b";
    private static final Pattern IP_PATTERN = Pattern.compile(IP_REGEX);
    private static final List<String> PHONE_MAY_BE = Arrays.asList("联系","致电","回电","号码","拨号","来电","拨打","电话","咨询","023-","023");

    private static final Map<String,String> HEADER_MAP = new HashMap<>();
    static {
        HEADER_MAP.put("accept","application/json, text/javascript, */*; q=0.01");
        HEADER_MAP.put("accept-encoding","gzip, deflate, br, zstd");
        HEADER_MAP.put("accept-language","zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6");
        HEADER_MAP.put("connection","keep-alive");
        HEADER_MAP.put("content-type","application/x-www-form-urlencoded; charset=UTF-8");
        HEADER_MAP.put("cookie",COOKIE);
        HEADER_MAP.put("host","mas.10086.cn");
        HEADER_MAP.put("origin","https://mas.10086.cn");
        HEADER_MAP.put("referer","https://mas.10086.cn/ec/cmEcBill/cmEcBill.do?_=1a4bffef230a44b283dd5336e39317fd");
        HEADER_MAP.put("sec-ch-ua","\"Microsoft Edge\";v=\"137\", \"Chromium\";v=\"137\", \"Not/A)Brand\";v=\"24\"");
        HEADER_MAP.put("sec-ch-ua-mobile","?0");
        HEADER_MAP.put("sec-ch-ua-platform","\"Windows\"");
        HEADER_MAP.put("sec-fetch-dest","empty");
        HEADER_MAP.put("sec-fetch-mode","cors");
        HEADER_MAP.put("sec-fetch-site","same-origin");
        HEADER_MAP.put("user-agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0");
        HEADER_MAP.put("x-requested-with","XMLHttpRequest");
    }

    private static final Map<String,String> DOWNLOAD_HEADER_MAP = new HashMap<>();
    static {
        DOWNLOAD_HEADER_MAP.put("accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7");
        DOWNLOAD_HEADER_MAP.put("accept-encoding","gzip, deflate, br, zstd");
        DOWNLOAD_HEADER_MAP.put("accept-language","zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6");
        DOWNLOAD_HEADER_MAP.put("cache-control","max-age=0");
        DOWNLOAD_HEADER_MAP.put("connection","keep-alive");
        DOWNLOAD_HEADER_MAP.put("cookie",COOKIE);
        DOWNLOAD_HEADER_MAP.put("host","mas.10086.cn");
        DOWNLOAD_HEADER_MAP.put("sec-ch-ua","\"Microsoft Edge\";v=\"137\", \"Chromium\";v=\"137\", \"Not/A)Brand\";v=\"24\"");
        DOWNLOAD_HEADER_MAP.put("sec-ch-ua-mobile","?0");
        DOWNLOAD_HEADER_MAP.put("sec-ch-ua-platform","\"Windows\"");
        DOWNLOAD_HEADER_MAP.put("sec-fetch-dest","document");
        DOWNLOAD_HEADER_MAP.put("sec-fetch-mode","navigate");
        DOWNLOAD_HEADER_MAP.put("sec-fetch-site","none");
        DOWNLOAD_HEADER_MAP.put("sec-fetch-user","?1");
        DOWNLOAD_HEADER_MAP.put("user-agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0");
        DOWNLOAD_HEADER_MAP.put("upgrade-insecure-requests","1");
    }


    public static void main(String[] args) throws Exception {
        // 每天都查询，看看是否有详情数据
        DateTime startDate = DateUtil.parse("2025-06-20", "yyyy-MM-dd");
        DateTime endTime = DateUtil.parse("2025-06-27", "yyyy-MM-dd");

        while (startDate.isBefore(endTime)) {
            long currentTimeMillis = System.currentTimeMillis();
            // 查询是否有数据
            String date = DateUtil.format(startDate, "yyyy-MM-dd");
            Boolean existsData = isExistsData(date);
            log.info("date:{},exists:{}",date,existsData);
            if(existsData){
                // 触发下载
                Boolean export = export(date);
                log.info("date:{},export status:{},consume time:{}",date,export,System.currentTimeMillis() - currentTimeMillis);
            }

            startDate.offset(DateField.DAY_OF_YEAR,1);
        }


        // 等待所有任务执行完成
        boolean isAllTaskOk = false;
        List<Map<String, Object>> allFileTask = new ArrayList<>();
        while (!isAllTaskOk) {
            allFileTask = getAllFileTask();
            isAllTaskOk = allFileTask.stream().filter(data -> data.get("fileName").toString().contains(DUAN_KOU)).allMatch(data -> {
                boolean isTaskOK = "1".equals(data.get("status").toString());
                // 任务状态需要正常
                if (!isTaskOK) {
                    return false;
                }

                // 任务存在实际数据
                String url = data.get("url").toString();
                String formattedUrl = FILE_DOWNLOAD_URL.formatted(url);
                try(HttpResponse response = HttpRequest.get(formattedUrl).headerMap(DOWNLOAD_HEADER_MAP,true).execute()){
                    return response.bodyBytes().length > 0;
                }
            });
            Thread.sleep(2000L);
        }

        // 创文件夹，初始写入对象
        boolean mkdirs = new File(BASE_FILE_URL + File.separator + ENTERPRISE_NAME + File.separator + "mas10086原始文件").mkdirs();
        log.info("{} create directory,status:{}",ENTERPRISE_NAME,mkdirs);

        Set<String> allHttp = new HashSet<>();
        Set<String> allPhone = new HashSet<>();

        // 写链接excel
        ExcelWriter excelWriterHttp = FastExcelFactory
                .write(BASE_FILE_URL + File.separator + ENTERPRISE_NAME +  File.separator + "包含链接的所有短信.xlsx")
                .excelType(ExcelTypeEnum.XLSX)
                .autoCloseStream(Boolean.FALSE)
                .build();
        WriteSheet writeSheetHttp = new WriteSheet();
        writeSheetHttp.setSheetNo(1);

        // 写号码excel
        ExcelWriter excelWriterPhone = FastExcelFactory
                .write(BASE_FILE_URL + File.separator + ENTERPRISE_NAME + File.separator + "包含号码的所有短信.xlsx")
                .excelType(ExcelTypeEnum.XLSX)
                .autoCloseStream(Boolean.FALSE)
                .build();
        WriteSheet writeSheetPhone = new WriteSheet();
        writeSheetPhone.setSheetNo(1);


        // 每个任务都下载文件
        for (Map<String, Object> task : allFileTask) {
            String url = task.get("url").toString();
            if(task.get("fileName").toString().contains(DUAN_KOU)){
                String formattedUrl = FILE_DOWNLOAD_URL.formatted(url);
                downloadFileAndAnalyzeWrite(formattedUrl,excelWriterHttp,writeSheetHttp,excelWriterPhone,writeSheetPhone,allHttp,allPhone);
            }
        }

        // 单独写链接
        List<List<String>> allHttpDataList = allHttp
                .stream()
                .map(data -> {
                    List<String> dataList = new ArrayList<>();
                    dataList.add(data);
                    return dataList;
                })
                .toList();
        FastExcelFactory
                .write(BASE_FILE_URL + File.separator + ENTERPRISE_NAME + File.separator + "所有的链接.xlsx")
                .excelType(ExcelTypeEnum.XLSX)
                .sheet(0)
                .sheetName("链接")
                .doWrite(allHttpDataList);


        // 单独写号码
        List<List<String>> allPhoneDataList = allPhone
                .stream()
                .map(data -> {
                    List<String> dataList = new ArrayList<>();
                    dataList.add(data);
                    return dataList;
                })
                .toList();
        FastExcelFactory
                .write(BASE_FILE_URL + File.separator + ENTERPRISE_NAME + File.separator + "所有的电话.xlsx")
                .excelType(ExcelTypeEnum.XLSX)
                .sheet(0)
                .sheetName("电话")
                .doWrite(allPhoneDataList);


        excelWriterHttp.finish();
        excelWriterPhone.finish();
    }

    private static Boolean isExistsData(String date) throws JsonProcessingException {
        Map<String,Object> formMap = new HashMap<>();
        formMap.put("formMap","");
        formMap.put("starttime",date);
        formMap.put("dc","%s,%s,optgroup_sms".formatted(MODE,DUAN_KOU));
        formMap.put("mobile","");
        formMap.put("pageIndex","1");
        formMap.put("pageSize","5");


        try(HttpResponse response = HttpUtil
                .createPost("https://mas.10086.cn/ec/cmEcBill/billList.ajax")
                .headerMap(HEADER_MAP, true)
                .form(formMap)
                .execute()){
            String body = response.body();
            Map<String, Object> responseMap = OBJECT_MAPPER.readValue(body, new TypeReference<>() {});
            Integer totalCount = (Integer)responseMap.get("totalCount");
            return totalCount > 0;
        }
    }

    @SuppressWarnings("unchecked")
    private static Boolean export(String date) throws JsonProcessingException {
        Map<String,Object> formMap = new HashMap<>();
        formMap.put("formMap","");
        formMap.put("starttime",date);
        formMap.put("dc","%s,%s,optgroup_sms".formatted(MODE,DUAN_KOU));
        formMap.put("mobile","");
        formMap.put("export","true");
        formMap.put("msgType","sms");

        try (HttpResponse response = HttpUtil
                .createPost("https://mas.10086.cn/ec/cmEcBill/daochu.ajax?")
                .headerMap(HEADER_MAP, true)
                .form(formMap)
                .execute()) {
            String body = response.body();
            Map<String, Object> responseMap = OBJECT_MAPPER.readValue(body, new TypeReference<>() {});
            Map<String, Object> result = (Map<String, Object>)responseMap.get("parameters");
            return "true".equals(result.get("result").toString());
        }
    }

    @SuppressWarnings("unchecked")
    private static List<Map<String, Object>> getAllFileTask() throws JsonProcessingException{
        Map<String,Object> formMap = new HashMap<>();
        formMap.put("centerBusinessType","01");
        formMap.put("pageIndex",1);
        formMap.put("pageSize","500");

        try(HttpResponse response = HttpUtil
                .createPost("https://mas.10086.cn/ec/downloadCenter/bill/list.ajax")
                .headerMap(HEADER_MAP, true)
                .form(formMap)
                .execute()) {
            String body = response.body();
            Map<String, Object> responseMap = OBJECT_MAPPER.readValue(body, new TypeReference<>() {});
            return  (List<Map<String, Object>>)responseMap.get("list");
        }
    }

    private static void downloadFileAndAnalyzeWrite(String filePath,
                                                    ExcelWriter excelWriterHttp,
                                                    WriteSheet writeSheetHttp,
                                                    ExcelWriter excelWriterPhone,
                                                    WriteSheet writeSheetPhone,
                                                    Set<String> allHttp,
                                                    Set<String> allPhone) throws Exception {
        // 文件名
        String[] split = filePath.split("/");
        String fileWriteName = URLDecoder.decode(URLDecoder.decode(split[split.length - 1], StandardCharsets.UTF_8), StandardCharsets.UTF_8);

        // 记录所有的匹配链接和短信
        List<LinkedHashMap<Integer,String>> matchHttpData = new ArrayList<>();
        List<LinkedHashMap<Integer,String>> matchPhoneData = new ArrayList<>();

        // 下载文件
        try (HttpResponse response = HttpRequest.get(filePath).headerMap(DOWNLOAD_HEADER_MAP,true).execute();
             FileOutputStream outputStream = new FileOutputStream(BASE_FILE_URL + File.separator + ENTERPRISE_NAME + File.separator + "mas10086原始文件" + File.separator + fileWriteName);
             FileOutputStream outputNewRecordStream = new FileOutputStream(BASE_FILE_URL + File.separator + ENTERPRISE_NAME + File.separator + "mas10086原始文件" + File.separator + "拼接数据-" + fileWriteName)) {
            byte[] bodyBytes = response.bodyBytes();

            // 每次下载就是一个文件
            outputStream.write(response.bodyBytes());
            outputStream.flush();

            // 读excel
            List<LinkedHashMap<Integer,String>> dataList = FastExcel.read(new ByteArrayInputStream(bodyBytes)).doReadAllSync();

            // 分组
            Map<String, List<LinkedHashMap<Integer, String>>> groupMap = dataList.stream().collect(Collectors.groupingBy(data -> {
                String content = data.get(3);
                content = content.substring(0,content.indexOf(")") + 1);
                if(content.startsWith("(") && content.endsWith(")")){
                    return data.get(0) + data.get(1);
                } else {
                    return data.get(0) + data.get(1) + UUID.randomUUID();
                }
            }));


            List<LinkedHashMap<Integer, String>> newDataList = new ArrayList<>();

            // 匹配
            groupMap.forEach((key, value) -> {
                String content;
                // 超过1条 需要拼接
                if(value.size() > 1){
                    StringBuilder sb = new StringBuilder();
                    value
                            .stream()
                            .sorted(Comparator.comparing(data -> {
                                char charAt = data.get(3).charAt(1);
                                String string = String.valueOf(charAt);
                                try {
                                    return Integer.parseInt(string);
                                } catch (Exception e) {
                                    System.out.println(key);
                                    System.out.println(value);
                                    System.out.println(data.get(3));
                                    throw e;
                                }
                            }))
                            .forEach(data -> {
                                String contentThis = data.get(3);
                                String finalData = contentThis.substring(contentThis.indexOf(")") + 1);
                                sb.append(finalData);
                            });
                    content = sb.toString();
                }
                // 否则就是完整的数据
                else {
                    content = value.getFirst().get(3);
                }

                // 新的拼接的完整数据，写回excel
                LinkedHashMap<Integer, String> copyValue = new LinkedHashMap<>(value.getFirst());
                copyValue.put(3,content);
                newDataList.add(copyValue);

                // 包含网站，网站可以直接提取，所以放进集合
                boolean containsHttp = false;
                Matcher ipMatcher = IP_PATTERN.matcher(content);
                while (ipMatcher.find()) {
                    containsHttp = true;
                    allHttp.add(ipMatcher.group()); // 去掉尾部的点
                }
                if(content.contains("//")){
                    containsHttp = true;
                    int index = 0;
                    while ((index = content.indexOf("//", index)) != -1) {
                        int start = Math.max(0,index - 10);
                        int end = Math.min(start + 50, content.length());
                        String extracted = content.substring(start, end);
                        allHttp.add(extracted);
                        index = start + 11; // 防止死循环，继续向后查找
                    }
                }

                if(containsHttp){
                    value.getFirst().put(3,content);
                    matchHttpData.add(value.getFirst());
                }

                if((content.contains("联系") ||
                        content.startsWith("023-") ||
                        content.contains("致电") ||
                        content.contains("回电") ||
                        content.contains("号码") ||
                        content.contains("拨号") ||
                        content.contains("来电") ||
                        content.contains("拨打") ||
                        content.contains("电话")) && !content.contains("票据号码")){
                    value.getFirst().put(3,content);
                    matchPhoneData.add(value.getFirst());

                    // 提取号码
                    for (String mainWord : PHONE_MAY_BE) {
                        int index = 0;
                        while ((index = content.indexOf(mainWord, index)) != -1) {
                            int start = Math.max(0,index - 10);
                            int end = Math.min(start + 30, content.length());
                            String extracted = content.substring(start, end);
                            if(!extracted.contains("票据号码")){
                                allPhone.add(extracted);
                            }
                            index = start + 11; // 防止死循环，继续向后查找
                        }
                    }

                }
            });

            // 需要写入新的组装好的完整短信到excel
            FastExcelFactory.write(outputNewRecordStream).excelType(ExcelTypeEnum.XLSX).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).sheet().doWrite(newDataList);
        }
        // 写了不flush,续写
        excelWriterHttp.write(matchHttpData,writeSheetHttp);
        excelWriterPhone.write(matchPhoneData,writeSheetPhone);
    }
}
